Skip to content

feat: add anonymous chat identity (nym) system to spec - #9

Merged
grunch merged 2 commits into
mainfrom
docs/anonymous-identity-chat
Mar 23, 2026
Merged

feat: add anonymous chat identity (nym) system to spec#9
grunch merged 2 commits into
mainfrom
docs/anonymous-identity-chat

Conversation

@mostronatorcoder

@mostronatorcoder mostronatorcoder Bot commented Mar 23, 2026

Copy link
Copy Markdown
Contributor

Summary

Adds the pseudonym and avatar system from v1 to v2 specification. This feature ensures users never see real pubkeys during chat — instead they see memorable, deterministic identifiers.

The Feature

When a trade becomes active, each party is displayed with:

  1. Pseudonym: adjective-noun format (e.g., "shadowy-wizard", "noKYC-satoshi")
  2. Avatar: Colored circle with an icon inside

Both are deterministically derived from the trade pubkey:

  • Same pubkey → same nym + avatar
  • Different pubkeys → (usually) different nyms

Changes

spec.md

User Story 5 (Chat):

  • Acceptance scenario 8: Parties shown with deterministic nym + avatar
  • Acceptance scenario 9: Pseudonym format and avatar details

Functional Requirements:

  • FR-011a: Display with pseudonym + avatar from trade pubkey
  • FR-011b: Deterministic pseudonym generation
  • FR-011c: Deterministic avatar (icon + color)

Glossary:

  • Nym (Pseudonym): Definition with format and examples
  • Nym Avatar: Definition with icon/color derivation

.specify/v1-reference/NYM_IDENTITY.md (new)

Complete reference document with:

  • Algorithm (BigInt modulo for word selection)
  • Word lists (~46 adjectives, ~85 nouns)
  • Icon list (~37 Material icons)
  • Color generation (HSV with hue from pubkey)
  • Widget implementation code
  • Privacy considerations
  • v2 implementation notes (Rust vs Dart split)

Privacy

  • Users never see real pubkeys in UI
  • Nyms derived from trade keys (not identity keys)
  • In privacy mode, same user gets different nyms per trade
  • ~3,910 possible combinations — collisions acceptable for visual distinction

Source

Extracted from v1 implementation:

  • lib/shared/providers/avatar_provider.dart
  • lib/shared/providers/legible_handle_provider.dart

Summary by CodeRabbit

  • Documentation
    • Added documentation for the v1 chat identity system, which generates deterministic pseudonyms (adjective-noun format) and colored avatars for trade participants based on their public keys.
    • Updated specification with formal chat-UI requirements for displaying participant identities during active trades.

Adds the pseudonym and avatar system from v1 to v2 spec.

## Changes to spec.md

### User Story 5 (Chat)
- Added acceptance scenarios 8 & 9 for nym display
- Each party shown with deterministic pseudonym + avatar

### Functional Requirements
- FR-011a: Pseudonym + avatar from trade pubkey
- FR-011b: Deterministic pseudonym generation (adjective-noun)
- FR-011c: Deterministic avatar (colored icon)

### Glossary
- Added 'Nym (Pseudonym)' definition
- Added 'Nym Avatar' definition

## New Reference Document
- .specify/v1-reference/NYM_IDENTITY.md
  - Full algorithm documentation
  - Word lists (adjectives, nouns, icons)
  - Color generation (HSV from pubkey)
  - Widget implementation reference
  - Privacy considerations
  - v2 implementation notes (Rust vs Dart split)
@grunch

grunch commented Mar 23, 2026

Copy link
Copy Markdown
Member

@coderabbitai review

@coderabbitai

coderabbitai Bot commented Mar 23, 2026

Copy link
Copy Markdown
Contributor
✅ Actions performed

Review triggered.

Note: CodeRabbit is an incremental review system and does not re-review already reviewed commits. This command is applicable only when automatic reviews are paused.

@coderabbitai

coderabbitai Bot commented Mar 23, 2026

Copy link
Copy Markdown
Contributor

Important

Review skipped

Bot user detected.

To trigger a single review, invoke the @coderabbitai review command.

⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: 4a810f6c-74a4-4f86-8e51-68dc4b50c75a

You can disable this status message by setting the reviews.review_status to false in the CodeRabbit configuration file.

Use the checkbox below for a quick retry:

  • 🔍 Trigger review

Walkthrough

Two documentation files introduce a deterministic pseudonym and avatar system that generates unique display identities from users' public keys. The system uses algorithmic selection from word lists and icon sets to create consistent, collision-aware chat identities with privacy considerations and implementation specifications.

Changes

Cohort / File(s) Summary
Nym Identity System Documentation
.specify/v1-reference/NYM_IDENTITY.md, specs/001-mostro-p2p-client/spec.md
Added comprehensive reference documentation for deterministic nym pseudonym and avatar generation from hex pubkeys, including BigInt-based modulo selection algorithms for adjectives/nouns, icon selection, HSV color derivation, Flutter widget outline, and privacy considerations. Updated main specification with formal requirements (FR-011a/b/c) and key entity definitions for Nym (Pseudonym) and Nym Avatar.

Estimated code review effort

🎯 2 (Simple) | ⏱️ ~12 minutes

Poem

🐰 A hop through pubkeys so grand,
Where adjectives and nouns are planned,
Each trader gets a colorful guise,
A bunny smile meets curious eyes,
Deterministic magic—no surprise! ✨

🚥 Pre-merge checks | ✅ 3
✅ Passed checks (3 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title accurately and concisely summarizes the main change: adding a deterministic nym (pseudonym) and avatar identity system to the specification.
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch docs/anonymous-identity-chat

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

🧹 Nitpick comments (2)
.specify/v1-reference/NYM_IDENTITY.md (2)

130-136: Privacy model is sound; consider clarifying collision implications.

The privacy considerations are well-reasoned:

  • ✅ Deterministic generation without reversibility
  • ✅ Trade-key derivation ensures privacy mode isolation
  • ✅ Acknowledged collision acceptance for single-trade context

Minor style fix: Line 135 should be "Trade-key-based" (hyphenated) per the static analysis hint.

Optional enhancement: With ~3,910 combinations, the birthday paradox suggests a 50% collision probability with approximately 63 simultaneous users across all trades in the network. While the document correctly states this is acceptable for visual distinction within a single trade, it might be worth noting that collision rates will be higher in busy deployments. This doesn't impact security but helps set expectations for visual uniqueness.

📝 Proposed clarification
-4. **Trade-key based**: Nyms are derived from trade keys, not identity keys. In privacy mode, each trade uses a different key, so the same user gets different nyms across trades.
+4. **Trade-key-based**: Nyms are derived from trade keys, not identity keys. In privacy mode, each trade uses a different key, so the same user gets different nyms across trades. Note: With ~3,910 combinations, collisions become likely as the network grows (50% probability with ~63 concurrent participants across all active trades), but this is acceptable since nyms are only used for visual distinction within a single trade, not for authentication.
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In @.specify/v1-reference/NYM_IDENTITY.md around lines 130 - 136, Change the
phrase "Trade-key based" to the hyphenated form "Trade-key-based" in the Privacy
Considerations section (the line describing that nyms are derived from trade
keys). Locate the sentence referencing trade-key derivation (the one starting
with "Trade-key based") and replace it with "Trade-key-based" to satisfy the
static analysis/style hint.

137-154: Clarify implementation boundary for icon and color selection.

The implementation notes suggest word selection happens in Rust, but icon and color selection could be in either Rust or Dart (line 148: "can also be in Rust if preferred"). This creates ambiguity for implementers.

Recommendation: For consistency, testability, and determinism guarantees, all deterministic selection logic (words, icons, colors) should be implemented in Rust:

  • Ensures identical behavior across platforms
  • Makes cross-client compatibility easier to verify
  • Concentrates deterministic logic in one tested layer
  • Dart only handles rendering the already-selected components
📋 Proposed clarification
 ### Dart Side
-Only the avatar widget needs Dart implementation:
+Only the avatar widget rendering needs Dart implementation:
 - Receives the generated nym string from Rust
-- Handles icon/color selection (can also be in Rust if preferred)
+- Receives the selected icon identifier and color value from Rust
 - Renders the CircleAvatar widget
+
+**Recommendation**: Implement icon and color selection in Rust alongside word selection to ensure determinism is testable and consistent across all platforms.
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In @.specify/v1-reference/NYM_IDENTITY.md around lines 137 - 154, The notes are
ambiguous about whether icon/color selection belongs in Rust or Dart; make
deterministic selection fully handled in Rust alongside the existing nym
generation (i.e., extend the Rust-side API exposed via flutter_rust_bridge to
return the nym string plus the chosen icon identifier and color), and update the
Dart avatar widget to only accept the nym, icon id, and color and render the
CircleAvatar; also update tests referenced in NYM_IDENTITY (nym generation,
icon/color determinism, and visual regression inputs) to assert Rust-produced
words, icon ids, and colors are stable and consistent across platforms.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In @.specify/v1-reference/NYM_IDENTITY.md:
- Around line 103-128: The NymAvatar reference sets the Icon color to the same
value returned by pickNymColor(pubkeyHex), which makes the icon invisible
against the outer CircleAvatar; update the widget so the inner CircleAvatar has
an explicit contrasting backgroundColor (e.g., a light/neutral color) and/or set
the Icon color to a contrasting value (e.g., white or the inverse of
pickNymColor(pubkeyHex)), and update the specification description accordingly;
locate the fix in the NymAvatar StatelessWidget where CircleAvatar, inner
CircleAvatar, Icon, pickNymColor(pubkeyHex) and pickNymIcon(pubkeyHex) are used.

---

Nitpick comments:
In @.specify/v1-reference/NYM_IDENTITY.md:
- Around line 130-136: Change the phrase "Trade-key based" to the hyphenated
form "Trade-key-based" in the Privacy Considerations section (the line
describing that nyms are derived from trade keys). Locate the sentence
referencing trade-key derivation (the one starting with "Trade-key based") and
replace it with "Trade-key-based" to satisfy the static analysis/style hint.
- Around line 137-154: The notes are ambiguous about whether icon/color
selection belongs in Rust or Dart; make deterministic selection fully handled in
Rust alongside the existing nym generation (i.e., extend the Rust-side API
exposed via flutter_rust_bridge to return the nym string plus the chosen icon
identifier and color), and update the Dart avatar widget to only accept the nym,
icon id, and color and render the CircleAvatar; also update tests referenced in
NYM_IDENTITY (nym generation, icon/color determinism, and visual regression
inputs) to assert Rust-produced words, icon ids, and colors are stable and
consistent across platforms.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: 5c08e116-7d12-4f8d-a5e9-ae537ba29a76

📥 Commits

Reviewing files that changed from the base of the PR and between a5b2e1e and 127e5d1.

📒 Files selected for processing (2)
  • .specify/v1-reference/NYM_IDENTITY.md
  • specs/001-mostro-p2p-client/spec.md

Comment thread .specify/v1-reference/NYM_IDENTITY.md Outdated
Fixes:
1. Fixed invisible icon bug - v1 used same color for bg and icon.
   v2 uses white icon on colored background for contrast.
2. Hyphenated 'Trade-key-based' per style guide.

Implementation clarified:
- ALL deterministic logic must be in Rust (nym, icon_index, color_hue)
- Dart only renders the widget with values from Rust
- Added Rust API struct: NymIdentity { pseudonym, icon_index, color_hue }
- Added Rust generate_nym() function signature
- Updated Dart widget to receive NymIdentity from Rust

Testing expanded:
- Rust unit tests for determinism and known values
- Flutter widget tests for rendering
- Golden tests for visual regression
@grunch
grunch merged commit ccdffb7 into main Mar 23, 2026
1 check passed
@grunch
grunch deleted the docs/anonymous-identity-chat branch March 23, 2026 15:00
codaMW pushed a commit to codaMW/app that referenced this pull request Jul 30, 2026
…est harness

The spec said the purpose was to "test the daemon implementation end-to-end".
That is a milestone, not the goal. The goal is Cashu shipped to real users in
both mostrod and this client, so a user can choose whether to trade on a node
that settles over Cashu or one that settles over Lightning. Both backends are
first-class and permanent.

Worth correcting because the two framings disagree exactly where it is
expensive to be wrong. New §1.1 spells out where, but the load-bearing ones:

- The wallet holds user funds. Ecash is bearer, so a lost wallet DB is lost
  money and backup/restore is a release requirement, not polish.
- Users never see the dev override, so detection has to work off the node's
  own advertisement — which promotes the upstream 38385 tags from convenience
  to release blocker (risk MostroP2P#3).
- The mint is a trust assumption users did not have in Lightning mode. If the
  choice is theirs it has to be informed, so the mint belongs next to the node
  wherever one is picked, before funds move, not after (risk MostroP2P#9).
- Web is first-class here, so "Cashu not available on web" would make the
  user's node choice depend on their platform.

Consequently Wave 4 is renamed from "optional hardening" to "required before
general availability", and C10 is split into release-blocking (backup/restore,
NUT-07 reconciliation, in-flight restore, locktime countdowns) versus actual
polish. Phase order and the dependency graph are untouched — what changed is
which phases are optional.

Also adds a release-acceptance row to the testing strategy for the paths only
a real user reaches, and records early evidence that cdk does target wasm, so
C9's open question is the storage backend rather than the crate.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant